from helper import *

import wx
import markdown, textile, re
import copy


# ( title, text_color, bg_color, link_color, vlink_color, alink_color, body )
html_template = """
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
	<HEAD>
		<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
		<TITLE>%s</TITLE>
	</HEAD>
	<BODY TEXT="#%s" BGCOLOR="#%s" LINK="#%s" VLINK="#%s" ALINK="#%s">
		%s
	</BODY>
</HTML>
"""
class NoteVListBox(wx.VListBox):		
	def OnDrawItem(self, dc, rect, n):
		selected = False
		if self.GetSelection() == n:
			c = self.highlight_text
			ignored = self.ignored_selection
			selected = True
		else:
			ignored = self.ignored
			c = self.GetForegroundColour()
		dc.SetFont(self.GetFont())
		dc.SetTextForeground(c)
		
		offset = 4
		rect.SetX( rect.GetX() + offset )
		rect.SetWidth( rect.GetWidth() - 2*offset )		
		
		note = self.note_list[n]
		app = wx.GetApp()
		note_controller = app.note
		if selected and app.revision > 0:
			# get current revision
			note = note_controller.history(note, app.revision)
		smart_header = note_controller.get_smart_header(note)
		
		shadow_rect = None
		shadow_text = None
		
		if n > 0:
			last_note = self.note_list[n-1]
			last_smart_header = note_controller.get_smart_header(last_note)
			same_till = self.find_common(last_smart_header['header'], smart_header['header'])
			
			if same_till >= 0:
				header = smart_header['header']
				smart_header['header'] = header[same_till+2:]
				
				offset = self.GetTextExtent(header[:same_till+2])[0]
				shadow_text = header[:same_till + 2]
				shadow_rect = wx.Rect(rect.GetX(), rect.GetY(), rect.GetWidth(), rect.GetHeight())
				shadow_rect.SetWidth( offset )
				
				rect.SetX( rect.GetX() + offset)
				rect.SetWidth( rect.GetWidth() - offset )
				
		head = smart_header['revision'] + smart_header['header'] + smart_header['markup']
		body = note_controller.get_body(note)
		content = '\n'.join( (head + body).split('\n')[:1] )
		

		
		dc.DrawLabel(content, rect, wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL)
		
		if shadow_rect:
			dc.SetTextForeground(ignored)
			dc.DrawLabel(shadow_text, shadow_rect,	wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL)

	def find_common(self, str1, str2):
		list1 = str1.split(config.sep)
		list2 = str2.split(config.sep)
		
		if not list1 or not list2:
			return -1
			
		if len(list1) < len(list1):
			left = list1
			right = list2
		else:
			left = list2
			right = list1
		
		same_till = -1
		for index in range(len(left)):
			if left[index] == right[index]:
				same_till = index
			else:
				break
		return len( config.sep.join(list1[:same_till + 1] ) ) - 1
		
	def OnMeasureItem(self, n):
		height = 0
		for line in self.note_list[n]['content'].split('\n')[:1]:
			# +l to make height for empty line 
			w, h = self.GetTextExtent(line+'l')
			height += h
		return height + 20

	def update_note_list(self, note_list):
		self.Clear()
		self.Refresh()
		self.note_list = note_list
		self.SetItemCount(len(note_list))
		
	def OnDrawBackground(self, dc, rect, n):
		if self.GetSelection() == n:
			c = self.highlight_background
		else:
			c = self.GetBackgroundColour()
			
		brush = wx.Brush(c)
		dc.SetBrush(brush)
		dc.SetPen(wx.TRANSPARENT_PEN)
		if self.GetSelection() == n:
			dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)









class ListFrame(wx.MiniFrame):
	def __init__(self, parent, title, pos, size):
		wx.Frame.__init__(self, parent, -1, title, pos=pos, size=size, style=wx.NO_BORDER|wx.STAY_ON_TOP)
		

		
		#-------------------------------------------------------------------------
		# Panel
		#-------------------------------------------------------------------------		
		panel = wx.Panel(self, size=size)

		border = 0
		new_size = (size[0]-border * 2, size[1]-border * 2 - 4)
		note_vlistbox = NoteVListBox(self, -1, size=new_size)
		os = wx.GetOsDescription()		  
		if re.search('Windows', os, re.I):
			note_vlistbox.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.NORMAL))
			
		#note_vlistbox.SetFont(wx.Font(16, wx.MODERN, wx.NORMAL, wx.LIGHT))
		note_vlistbox.highlight_text = wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT)
		note_vlistbox.highlight_background = self.GetBackgroundColour()
		note_vlistbox.note_list = []
		note_vlistbox.SetItemCount(0)

		self.note_vlistbox = note_vlistbox
		
		
		#-------------------------------------------------------------------------
		# Binding
		#-------------------------------------------------------------------------
		self.Bind(wx.EVT_LISTBOX, self.OnSelect, note_vlistbox)
		
		
		
		#-------------------------------------------------------------------------
		# Layout
		#-------------------------------------------------------------------------
		sizer = wx.BoxSizer(wx.VERTICAL)
		sizer.Add(note_vlistbox, 0, wx.EXPAND|wx.ALL, border)
		panel.SetSizer(sizer)
		panel.Layout()	
		self.panel = panel	
		
		self.note_list = []
		self.auto_sense = False
		self.note_cache = {}
		
	def update_note_list(self, note_list, force = False):
		if not force and self.note_list == note_list:
			return

		old_note_list = self.note_list
		self.note_list = note_list
		
		app = wx.GetApp()
		
		# new note_list with items
		if note_list:
			# old note list with items
			if self.note_vlistbox.note_list:
				
				# get the previous index
				index = self.note_vlistbox.GetSelection()
				
				# update this list
				self.note_vlistbox.update_note_list(note_list)
				
				# item is actually selected
				if index >= 0 and old_note_list:
					
					note = old_note_list[index]
					new_index = -1

					for i in xrange(len(note_list)):
						if note_list[i]['id'] == note['id']:
							new_index = i
							break

					if new_index < 0:
						#new_index = ( index + 1 )% len(note_list)
						new_index = index % len(note_list)

					self.note_vlistbox.SetSelection(new_index)
				else:
					self.note_vlistbox.SetSelection(0)
			else:
				self.note_vlistbox.update_note_list(note_list)
				self.note_vlistbox.SetSelection(0)
			self.Show(1)
			self.update_selection()
		else:
			self.Show(0)
			app.display_frame.Show(0)
		
		
	def OnSelect(self, evt):
		if self.IsShown():
			self.update_selection()

		
	def update_selection(self):
		index = self.note_vlistbox.GetSelection()
		note = self.note_vlistbox.note_list[index]
		app = wx.GetApp()

		app.reset_revision(note)
		
		if app.revision >= 0:
			note = app.note.history(note, app.revision)
		
		
		if self.auto_sense:
			note = self.setup_markup(note)
		else:
			app.use_plain_display(note)
		
		display_frame = app.display_frame
		search_frame = app.search_frame
		
		if not display_frame.IsShown():
			display_frame.Show(1)
			search_frame.set_focus()
		

		
	def setup_markup(self, note):
		app = wx.GetApp()

		# decide mark up
		markup = app.note.get_markup(note)
		if markup in ['markdown', 'textile']:
			if self.note_cache.has_key(note['id']) and self.note_cache[note['id']]['content'] == note['content']:
				# use cache data
				html = self.note_cache[note['id']]['html']
			else:
				body =	app.note.get_body(note)
				if markup == 'markdown':
					body = markdown.markdown(body, encoding='utf-8' )
				elif markup == 'textile':
					body = textile.textile(body.encode('utf-8'), encoding='utf-8')
				html = self.fill_html(app.note.get_header(note), body)
				self.note_cache[note['id']] = {'content' : note['content'], 'html' : html}
			note['html'] = html
			
			app.use_pretty_display(note)
		else:
			app.use_plain_display(note)
		return note
		
	def fill_html(self, title, body):
		# ( title, text_color, bg_color, link_color, vlink_color, alink_color, body )
		text_color = get_html_color('foreground')
		bg_color = get_html_color('background')
		link_color = vlink_color = alink_color = get_html_color('highlight', 1)
		return html_template % ( title, text_color, bg_color, link_color, vlink_color, alink_color, body )

		
	def enable_auto_sense(self, enable = True):
		if enable:
			self.auto_sense = True
		else:
			self.auto_sense = False
		
	def set_colors(self, color_dict):
	#		self.SetBackgroundColour(color_converter(color_dict['trans']))
		self.panel.SetBackgroundColour(get_fake_color('background'))
		self.note_vlistbox.SetBackgroundColour(get_fake_color('background'))
		self.note_vlistbox.SetForegroundColour(get_color('foreground'))
		
		self.note_vlistbox.highlight_text = get_color('selection', 1)
		self.note_vlistbox.highlight_background = get_color('selection', 0)
		
		self.note_vlistbox.ignored = get_color('ignored')
		self.note_vlistbox.ignored_selection = get_color('ignored_selection')